package com.kjlink.widget.monitoring.report;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.kjlink.widget.monitoring.enums.EventTypeEnum;
import com.kjlink.widget.monitoring.model.MonitorDataModel;
import com.kjlink.widget.monitoring.processor.MonitorEventSender;
import com.kjlink.widget.monitoring.report.handler.BaseMonitorDataBuildHandler;

/**
 * 描述:
 * 监控事件上报门面
 *
 * @author Vic.xu
 * @since 2025-08-21 14:05
 */
public class MonitorEventReportFacade {
    private int maxExceptionMessageLength = 512;

    private static final Logger LOGGER = LoggerFactory.getLogger(MonitorEventReportFacade.class);

    private MonitorEventSender monitorEventSender;

    private Map<EventTypeEnum, BaseMonitorDataBuildHandler> buildHandlerMap;

    private Consumer<MonitorDataModel> commonFill;

    private Supplier<Boolean> send = () -> true;


    public MonitorEventReportFacade(MonitorEventSender monitorEventSender) {
        this.monitorEventSender = monitorEventSender;
        this.buildHandlerMap = new HashMap<>();
    }

    public void setBuildHandlers(List<BaseMonitorDataBuildHandler> buildHandlers) {
        if (buildHandlers != null) {
            buildHandlers.forEach(handler -> buildHandlerMap.put(handler.eventType(), handler));
        }
    }

    /**
     * 通用填充, 在自定义填充之前
     */
    public void setCommonFill(Consumer<MonitorDataModel> commonFill) {
        this.commonFill = commonFill;
    }

    public void setSend(Supplier<Boolean> send) {
        this.send = send;
    }

    /**
     * 主要在注解中调用
     *
     * @param model
     * @see com.kjlink.widget.monitoring.aspect.MonitorEventReportAspect#afterThrowing(JoinPoint, Throwable)
     */
    public void fillDataAndSend(MonitorDataModel model) {
        try {
            if (!send.get()) {
                LOGGER.info("send event switch not open!");
                return;
            }
            Assert.notNull(model, "MonitorDataModel can not be null, when build Data");
            // 1 先调用 通用数据填充
            if (commonFill != null) {
                commonFill.accept(model);
            }
            // 2 再 获取各个业务的数据填充处理逻辑 进行数据填充
            BaseMonitorDataBuildHandler handler = buildHandlerMap.get(model.getEventType());
            if (handler != null) {
                handler.fill(model);
            } else {
                LOGGER.warn("No build handler for eventType: {}", model.getEventType());
            }
            // 3 发送事件 到redis
            monitorEventSender.sendEvent(model);
        } catch (Exception ex) {
            LOGGER.error("fillDataAndSend error", ex);
        }
    }

    /**
     * 一般在ctrl的手动的catch调用
     */

    public void fillDataAndSend(EventTypeEnum eventType, String businessId, String exMessage, String eventCode) {
        try {
            MonitorDataModel model = new MonitorDataModel();
            model.setEventType(eventType);
            model.setBusinessId(businessId);
            // exception
            model.setException(org.apache.commons.lang3.StringUtils.abbreviate(exMessage, maxExceptionMessageLength));
            model.setEventCode(eventCode);
            this.fillDataAndSend(model);
        } catch (Exception ex) {
            LOGGER.error("fillDataAndSend error", ex);
        }

    }

    /**
     * 一般在ctrl的手动的catch调用
     */
    public void fillDataAndSend(EventTypeEnum eventType, String businessId, Throwable e) {
        try {
            this.fillDataAndSend(eventType, businessId, e.getMessage(), e.getClass().getName());
        } catch (Exception ex) {
            LOGGER.error("fillDataAndSend error", ex);
        }
    }

}
